home *** CD-ROM | disk | FTP | other *** search
Text File | 1997-06-13 | 11.4 KB | 429 lines | [TEXT/CWIE] |
-
- //===============================================================================
- //
- // GetMonitorProfile.c
- //
- //===============================================================================
-
-
- #include <CMApplication.h>
- #include <StandardFile.h>
- #include <LowMem.h>
- #include "GetMonitorProfile.h"
-
-
- #define kProfileType 'prof'
- #define kXYZProfileID -16011
- #define custGFDialogID -4048
- #define itemSFProfileName 11
-
-
- typedef struct
- {
- OSType dataType;
- FSSpec lastSpec; // last file spec that we used to display profile name
- StandardFileReply reply; // current reply for CustomGetFile
- } FilterDataStructure;
-
-
- static pascal Boolean TheFileFilter (CInfoPBPtr, FilterDataStructure *);
- static pascal short TheDialogHook (short item, DialogRef, FilterDataStructure *);
- static void CSProfileInfoString (FSSpec *, Str255);
- static void SetSFDefaults (short, long);
- static void GetSFDefaults (short *, long *);
- static OSErr ReadProfileCM2Header(FSSpec *, CM2Header *);
- static OSErr ResolveFSSpec (FSSpec *, FSSpec *);
- static OSErr IsAliasFile (const FSSpec *, Boolean *, Boolean *);
- static OSErr ResolveAliasFileMountOption (FSSpec *, Boolean, Boolean *, Boolean *, Boolean);
-
-
- //===================================================================== Functions
- //--------------------------------------------------------------------- StandardGetProfile
-
- OSErr StandardGetProfile ( CMProfileLocation *profLoc, Boolean *sfGood,
- OSType inputDataType)
- {
- FilterDataStructure fds;
- Point position;
- OSType profileType;
- CMError err;
- FileFilterYDUPP fileUPP;
- DlgHookYDUPP hookUPP;
- long oldDirID;
- short oldVRefNum;
-
- profileType = kProfileType;
- err = noErr;
- *sfGood = false;
-
- // Set Standard File directory to be ColorSync profiles folder.
- GetSFDefaults( &oldVRefNum, &oldDirID );
-
- fds.lastSpec.name[0] = 0;
- fds.dataType = nil;
- position.h = position.v = -1;
-
- fileUPP = NewFileFilterYDProc(TheFileFilter);
- hookUPP = NewDlgHookYDProc(TheDialogHook);
-
- // Do standard file, with our filters causing only valid system
- // profiles to be displayed.
- CustomGetFile(fileUPP, 1, &profileType, &fds.reply, custGFDialogID, position, hookUPP,
- 0L, 0, 0L, &fds);
-
- DisposeRoutineDescriptor(fileUPP);
- DisposeRoutineDescriptor(hookUPP);
-
- // Restore Standard File default directory.
- SetSFDefaults(oldVRefNum,oldDirID);
-
- if (fds.reply.sfGood)
- {
- *sfGood = true;
- profLoc->locType = cmFileBasedProfile;
- profLoc->u.fileLoc.spec = fds.reply.sfFile;
-
- }
-
- return err;
- }
-
- #pragma mark -------------------- Private Functions
- //===================================================================== Private Functions
- //--------------------------------------------------------------------- TheFileFilter
- // Our file filter for allowing only valid system profiles to be displayed
- // in the Standard File dialog.
-
- static pascal Boolean TheFileFilter (CInfoPBPtr pb, FilterDataStructure *fds)
- {
- Boolean goodFile;
- OSErr err;
- FSSpec spec,fromSpec;
- CM2Header hdr2;
-
- goodFile = false;
- err = noErr;
-
- if ( (*pb).hFileInfo.ioFlFndrInfo.fdType != kProfileType)
- err = 1; // this should never happen
-
- if (!err)
- err = FSMakeFSSpec( (*pb).hFileInfo.ioVRefNum,
- (*pb).dirInfo.ioDrParID,
- (*pb).hFileInfo.ioNamePtr, &fromSpec);
-
- if (!err)
- err = ResolveFSSpec( &fromSpec, &spec );
-
- if (!err)
- err = ReadProfileCM2Header( &spec, &hdr2 );
-
- if (!err)
- if ((hdr2.CS2profileSignature == cmMagicNumber) &&
- (hdr2.profileVersion == cmCS2ProfileVersion) &&
- (fds->dataType == nil || fds->dataType==hdr2.dataColorSpace) )
- goodFile = true;
-
- return !goodFile;
- }
-
- //--------------------------------------------------------------------- TheDialogHook
- // During standard file null events, check to see if the user has changed
- // the current selection. If so, we need to update the profile name
- // string in the window. If nothing is selected, the string will end
- // up blank.
-
- static pascal short TheDialogHook (short item, DialogRef theDialogRef,
- FilterDataStructure *fds )
- {
- if (item == sfHookFirstCall)
- {
- UInt32 refcon;
- SInt32 csDirID;
- SInt16 csVRefNum;
-
- refcon = GetWRefCon((WindowRef)theDialogRef);
- if ( refcon == sfMainDialogRefCon )
- {
- if ( CMGetColorSyncFolderSpec(kOnSystemDisk, false, &csVRefNum, &csDirID) == noErr )
- {
- fds->reply.sfFile.vRefNum = csVRefNum;
- fds->reply.sfFile.parID = csDirID;
- fds->reply.sfFile.name[0] = 0;
- return sfHookChangeSelection;
- }
- }
- if ( refcon == sfLockWarnDialogRefCon )
- return 1; // simulate hit of OK button
- }
-
- if (item == sfHookNullEvent)
- {
- OSErr err;
- Str255 profName;
- FSSpec *old = &fds->lastSpec;
- FSSpec *new = &fds->reply.sfFile;
- FInfo fndrInfo;
-
- // First compare the new spec with the last one we looked at.
- if ( (new->vRefNum != old->vRefNum) ||
- (new->parID != old->parID) ||
- !EqualString(new->name,old->name,true,true) )
- {
- // OK, they are different. Save the new one.
-
- *old =*new;
-
- // Get the Info string. Note that if new is not a valid
- // filespec (as will be the case when nothing is selected),
- // we end up with an empty string.
- err = FSpGetFInfo(old,&fndrInfo);
- if (!err && (fndrInfo.fdType == kProfileType) )
- CSProfileInfoString(old,profName);
- else
- profName[0] = 0;
-
- // Save old again in case above changed it
- *old =*new;
-
- {
- Rect r;
- Handle textHdl;
- SInt16 itemType;
-
- GetDialogItem (theDialogRef, itemSFProfileName, &itemType, &textHdl, &r);
- SetDialogItemText (textHdl, profName);
- }
- }
- }
-
- return item;
- }
-
- //--------------------------------------------------------------------- CSProfileInfoString
-
- static void CSProfileInfoString ( FSSpec *spec, Str255 info )
- {
- CMProfileRef prof;
- CMError err;
-
- // Clear string first just to be safe.
- info[0] = 0;
-
- if (spec)
- {
- CMProfileLocation location;
- location.locType = cmFileBasedProfile;
- location.u.fileLoc.spec = *spec;
- err = CMOpenProfile(&prof,&location);
- }
- else
- err = CMGetSystemProfile(&prof);
-
- if (!err)
- {
- ScriptCode script;
- err = CMGetScriptProfileDescription(prof, info, &script); // in ProfileConvert.c
- CMCloseProfile(prof);
- }
- }
-
- //--------------------------------------------------------------------- SetSFDefaults
- // Jam the low-mem globals for StandardFile such that the dialog comes up
- // in the specified directory.
-
- static void SetSFDefaults ( short vRefNum, long dirID )
- {
- LMSetSFSaveDisk(-1 * vRefNum);
- LMSetCurDirStore(dirID);
- }
-
-
- //--------------------------------------------------------------------- GetSFDefaults
- // Get the low-mem globals for the directory that the StandardFile dialog
- // comes up in.
-
- static void GetSFDefaults ( short *vRefNum, long *dirID )
- {
- *vRefNum = -1 * LMGetSFSaveDisk();
- *dirID = LMGetCurDirStore();
- }
-
- //--------------------------------------------------------------------- ReadProfileCM2Header
-
- static OSErr ReadProfileCM2Header ( FSSpec *spec, CM2Header *hdr)
- {
- OSErr err=noErr;
- short refNum;
- long readSize;
-
- refNum = 0;
- readSize = sizeof(CM2Header);
-
- if (!spec || !hdr)
- err = paramErr;
-
- if (!err)
- err = FSpOpenDF( spec, fsRdPerm, &refNum);
-
- if (!err)
- err = FSRead( refNum, &readSize, (Ptr)hdr);
-
- if (refNum)
- (void) FSClose(refNum);
-
- return err;
- }
- //--------------------------------------------------------------------- ResolveFSSpec
-
- static OSErr ResolveFSSpec (FSSpec *fromSpec, FSSpec *toSpec)
- {
- OSErr err = noErr;
- Boolean isFolder;
- Boolean wasAlias;
-
- err = FSMakeFSSpec(fromSpec->vRefNum,fromSpec->parID, (StringPtr)
- &fromSpec->name,toSpec);
-
- if (!err)
- err = ResolveAliasFileMountOption( toSpec, true, &isFolder, &wasAlias, false);
- else
- err = noErr;
-
- return err;
- }
-
- //--------------------------------------------------------------------- IsAliasFile
-
- static OSErr IsAliasFile (const FSSpec *fileFSSpec, Boolean *aliasFileFlag,
- Boolean *folderFlag)
- {
- CInfoPBRec myCInfoPBRec;
- OSErr retCode;
-
- if (fileFSSpec == nil || aliasFileFlag == nil || folderFlag == nil)
- return paramErr;
-
- *aliasFileFlag = *folderFlag = false;
-
- // Get the item's catalog information.
- myCInfoPBRec.hFileInfo.ioCompletion = nil;
- myCInfoPBRec.hFileInfo.ioNamePtr = (StringPtr) &fileFSSpec->name;
- myCInfoPBRec.hFileInfo.ioVRefNum = fileFSSpec->vRefNum;
- myCInfoPBRec.hFileInfo.ioDirID = fileFSSpec->parID;
- myCInfoPBRec.hFileInfo.ioFVersNum = 0;
- myCInfoPBRec.hFileInfo.ioFDirIndex = 0;
-
- retCode = PBGetCatInfoSync(&myCInfoPBRec);
-
- // Set aliasFileFlag if the item is not a directory and the...
- // aliasFile bit is set.
- if (retCode == noErr)
- { // Check directory bit else check isAlias bit.
- if ((myCInfoPBRec.hFileInfo.ioFlAttrib & ioDirMask) != 0)
- *folderFlag = true;
- else if ((myCInfoPBRec.hFileInfo.ioFlFndrInfo.fdFlags & 0x8000) != 0)
- *aliasFileFlag = true;
- }
-
- return retCode;
- }
-
- //--------------------------------------------------------------------- ResolveAliasFileMountOption
-
- static OSErr ResolveAliasFileMountOption (FSSpec *fileFSSpec, Boolean resolveAliasChains,
- Boolean *targetIsFolder, Boolean *wasAliased, Boolean mountRemoteVols)
- {
- // Maximum number of aliases to resolve before giving up.
- #define MAXCHAINS 10
- FSSpec initFSSpec;
- Handle alisHandle;
- OSErr retCode;
- SInt16 myResRefNum, chainCount;
- Boolean updateFlag, foundFlag;
- Boolean wasAliasedTemp, specChangedFlag;
-
- if (fileFSSpec == nil || targetIsFolder == nil || wasAliased == nil)
- return paramErr;
-
- // So FSSpec can be restored in case of error.
- initFSSpec = *fileFSSpec;
- // Circular alias chain protection.
- chainCount = MAXCHAINS;
- // Resource file not open.
- myResRefNum = -1;
-
- *targetIsFolder = foundFlag = specChangedFlag = false;
-
- // Loop through chain of alias files.
- do
- {
- chainCount--;
-
- // Check if FSSpec is an alias file or a directory.
- // Note: targetIsFolder => NOT wasAliased.
- retCode = IsAliasFile(fileFSSpec, wasAliased, targetIsFolder);
- if (retCode != noErr || !(*wasAliased))
- break;
-
- // Get the resource file reference number.
- myResRefNum = FSpOpenResFile(fileFSSpec, fsCurPerm);
- retCode = ResError();
- if (myResRefNum == -1)
- break;
-
- // The first 'alis' resource in the file is the appropriate alias.
- alisHandle = Get1IndResource(rAliasType, 1);
- retCode = ResError();
- if (alisHandle == nil)
- break;
-
- // Load the resource explicitly in case SetResLoad(FALSE).
- LoadResource(alisHandle);
- retCode = ResError();
- if (retCode != noErr)
- break;
-
- retCode = FollowFinderAlias(fileFSSpec, (AliasHandle) alisHandle,
- mountRemoteVols, fileFSSpec, &updateFlag);
-
- // FollowFinderAlias returns nsvErr if volume not mounted.
- if (retCode == noErr)
- {
- if (updateFlag)
- {
- // The resource in the alias file needs updating.
- ChangedResource(alisHandle);
- WriteResource(alisHandle);
- }
-
- specChangedFlag = true;
-
- // In case of error, restore file spec.
- retCode = IsAliasFile(fileFSSpec, &wasAliasedTemp, targetIsFolder);
- if (retCode == noErr)
- // We're done unless it was an alias file and we're following a chain.
- foundFlag = !(wasAliasedTemp && resolveAliasChains);
-
- }
-
- CloseResFile(myResRefNum);
- myResRefNum = -1;
-
- } while (retCode == noErr && chainCount > 0 && !foundFlag);
-
- // Return file not found error for circular alias chains.
- if (chainCount == 0 && !foundFlag)
- retCode = fnfErr;
-
- // If error, close resource file and restore original FSSpec.
- if (myResRefNum != -1)
- CloseResFile(myResRefNum);
-
- if (retCode != noErr && specChangedFlag)
- *fileFSSpec = initFSSpec;
-
- return retCode;
- }
-
-